﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Cms.Domain
{
    [Serializable]
    public class Site : IComparable<Site>, IAuditable
    {
        private IList<Administrator> _administrators;
        private IList<string> _aliasDomains;
        private IList<Application> _applications;
        private IList<Category> _categories;
        private IList<Content> _content;
        private DetailTemplate _defaultDetailTemplate;
        private Locale _defaultLocale;
        private MasterTemplate _defaultMasterTemplate;
        private IList<DetailTemplate> _detailTemplates;
        private string _domain;
        private IList<Folder> _folders;
        private int _id;
        private IList<Locale> _locales;
        private IList<MasterTemplate> _masterTemplates;
        private IList<MediaFile> _mediaFiles;
        private IList<MediaFolder> _mediaFolders;
        private IList<Menu> _menus;
        private string _newsletterFolder;
        private string _noReplyEmail;
        private bool _online;
        private IList<Page> _pages;
        private string _rootMediaFolder;
        private IList<Stylesheet> _stylesheets;
        private IList<RssFeed> _rssFeeds;

        public Site()
        {
            _locales = new List<Locale>();
            _aliasDomains = new List<string>();
            _folders = new List<Folder>();
            _pages = new List<Page>();
            _masterTemplates = new List<MasterTemplate>();
            _detailTemplates = new List<DetailTemplate>();
            _content = new List<Content>();
            _stylesheets = new List<Stylesheet>();
            _mediaFolders = new List<MediaFolder>();
            _mediaFiles = new List<MediaFile>();
            _applications = new List<Application>();
            _categories = new List<Category>();
            _menus = new List<Menu>();
            _administrators = new List<Administrator>();
            _rssFeeds = new List<RssFeed>();
        }
        
        public virtual int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        public virtual string Domain
        {
            get { return _domain; }
            set { _domain = value; }
        }

        public virtual bool Online
        {
            get { return _online; }
            set { _online = value; }
        }
        
        public virtual Locale DefaultLocale
        {
            get { return _defaultLocale; }
            set { _defaultLocale = value; }
        }

        public virtual MasterTemplate DefaultMasterTemplate
        {
            get { return _defaultMasterTemplate; }
            set { _defaultMasterTemplate = value; }
        }

        public virtual DetailTemplate DefaultDetailTemplate
        {
            get { return _defaultDetailTemplate; }
            set { _defaultDetailTemplate = value; }
        }
        
        public virtual IList<Stylesheet> Stylesheets
        {
            get { return _stylesheets; }
            set { _stylesheets = value; }
        }
        
        public virtual string RootMediaFolder
        {
            get { return _rootMediaFolder; }
            set { _rootMediaFolder = value; }
        }
        
        public virtual string NewsletterFolder
        {
            get { return _newsletterFolder; }
            set { _newsletterFolder = value; }
        }
        
        public virtual string NoReplyEmail
        {
            get { return _noReplyEmail; }
            set { _noReplyEmail = value; }
        }

        public virtual IList<Locale> Locales
        {
            get { return _locales; }
            set { _locales = value; }
        }
        
        public virtual IList<string> AliasDomains
        {
            get { return _aliasDomains; }
            set { _aliasDomains = value; }
        }
        
        public virtual IList<Folder> Folders
        {
            get { return _folders; }
            set { _folders = value; }
        }

        public virtual IList<Page> Pages
        {
            get { return _pages; }
            set { _pages = value; }
        }
        
        public virtual IList<MasterTemplate> MasterTemplates
        {
            get { return _masterTemplates; }
            set { _masterTemplates = value; }
        }
        
        public virtual IList<DetailTemplate> DetailTemplates
        {
            get { return _detailTemplates; }
            set { _detailTemplates = value; }
        }
        
        public virtual IList<Content> Content
        {
            get { return _content; }
            set { _content = value; }
        }
        
        public virtual IList<MediaFolder> MediaFolders
        {
            get { return _mediaFolders; }
            set { _mediaFolders = value; }
        }
        
        public virtual IList<MediaFile> MediaFiles
        {
            get { return _mediaFiles; }
            set { _mediaFiles = value; }
        }
        
        public virtual IList<Application> Applications
        {
            get { return _applications; }
            set { _applications = value; }
        }
        
        public virtual IList<Category> Categories
        {
            get { return _categories; }
            set { _categories = value; }
        }
        
        public virtual IList<Menu> Menus
        {
            get { return _menus; }
            set { _menus = value; }
        }

        public virtual IList<Administrator> Administrators
        {
            get { return _administrators; }
            set { _administrators = value; }
        }

        public virtual IList<RssFeed> RssFeeds
        {
            get { return _rssFeeds; }
            set { _rssFeeds = value; }
        }

        public virtual Locale GetLocaleByUrlCode(string urlCode)
        {
            return _locales.FirstOrDefault(locale => locale.UrlCode.ToLower() == urlCode.ToLower());
        }
        
        public virtual IList<Folder> GetRootFolders()
        {
            return _folders.Where(f => f.Parent == null).ToList();
        }
        
        public virtual IList<Page> GetRootPages()
        {
            return _pages.Where(p => p.Folder == null).ToList();
        }
        
        public virtual bool CanFolderBeNamedAndMovedTo(int id, string name, Folder parent)
        {
            IList<Folder> parentLevelFolders = parent == null ? GetRootFolders() : parent.SubFolders;
            foreach (Folder f in parentLevelFolders)
            {
                if (f.Name.ToLower() == name.ToLower() && f.ID != id)
                    return false;
            }
            return true;
        }

        public virtual bool CanPageBeNamedAndMovedTo(int id, string filename, Folder folder)
        {
            IList<Page> siblingPages = folder == null ? GetRootPages() : folder.Pages;
            foreach (Page p in siblingPages)
            {
                if (p.Filename.ToLower() == filename.ToLower() && p.ID != id)
                    return false;
            }
            return true;
        }
        
        public virtual bool CanMasterTemplateBeNamedTo(int id, string name)
        {
            foreach (MasterTemplate mt in _masterTemplates)
            {
                if (mt.Name.ToLower() == name.ToLower() && mt.ID != id)
                    return false;
            }
            return true;
        }
        
        public virtual bool CanDetailTemplateBeNamedTo(int id, string name)
        {
            foreach (DetailTemplate dt in _detailTemplates)
            {
                if (dt.Name.ToLower() == name.ToLower() && dt.ID != id)
                    return false;
            }
            return true;
        }
        
        public virtual bool CanStylesheetBeNamedTo(int id, string name)
        {
            foreach (Stylesheet stylesheet in _stylesheets)
            {
                if (stylesheet.Name.ToLower() == name.ToLower() && stylesheet.ID != id)
                    return false;
            }
            return true;
        }
        
        public virtual bool CanLocaleHaveUrlCode(int localeID, string urlCode)
        {
            foreach (Locale locale in _locales)
            {
                if (locale.UrlCode.ToLower() == urlCode.ToLower() && locale.ID != localeID)
                    return false;
            }
            return true;
        }
        
        public virtual IList<MediaFolder> GetRootMediaFolders()
        {
            return _mediaFolders.Where(f => f.Parent == null).ToList();
        }

        public virtual IList<MediaFile> GetRootMediaFiles()
        {
            return _mediaFiles.Where(mf => mf.Folder == null).ToList();
        }

        public virtual bool CanMediaFolderBeNamedAndMovedTo(long id, string name, MediaFolder parent)
        {
            IList<MediaFolder> parentLevelFolders;
            if (parent == null)
                parentLevelFolders = GetRootMediaFolders();
            else
                parentLevelFolders = parent.SubFolders;
            foreach (MediaFolder f in parentLevelFolders)
            {
                if (f.Name.ToLower() == name.ToLower() && f.ID != id)
                    return false;
            }
            return true;
        }
        
        public virtual bool CanMediaFileBeNamedAndMovedTo(int id, string filename, MediaFolder folder)
        {
            IList<MediaFile> siblingFiles;
            if (folder == null)
                siblingFiles = GetRootMediaFiles();
            else
                siblingFiles = folder.Files;
            foreach (MediaFile f in siblingFiles)
            {
                if (f.Name.ToLower() == filename.ToLower() && f.ID != id)
                    return false;
            }
            return true;
        }

        public virtual MediaFolder GetMediaFolder(string pathWithoutRootMediaFolder)
        {
            foreach (MediaFolder folder in _mediaFolders)
                if (folder.GetVirtualPath().ToLower() == (_rootMediaFolder + "/" + pathWithoutRootMediaFolder).ToLower())
                    return folder;
            return null;
        }

        public virtual MediaFile GetMediaFile(string pathWithoutRootMediaFolder, string name)
        {
            MediaFolder folder = GetMediaFolder(pathWithoutRootMediaFolder);
            IList<MediaFile> files = folder == null ? GetRootMediaFiles() : folder.Files;
            return files.FirstOrDefault(file => file.Name.ToLower() == name.ToLower());
        }
        
        public virtual MediaFile GetRootMediaFile(string filename)
        {
            return GetMediaFile(string.Empty, filename);
        }
        
        public virtual IList<Category> GetRootCategories()
        {
            IList<Category> rootCategories = new List<Category>();
            foreach (Category c in _categories)
                if (c.Parent == null)
                    rootCategories.Add(c);
            return rootCategories;
        }

        public virtual bool CanCategoryBeNamedAndMovedTo(int id, string name, string folderName, Category parent)
        {
            IList<Category> parentLevelItems = parent == null ? GetRootCategories() : parent.SubCategories;
            return
                parentLevelItems.All(
                    c =>
                    (c.Name.ToLower() != name.ToLower() && c.FolderName.ToLower() != folderName.ToLower()) || c.ID == id);
        }

        public virtual int CompareTo(Site other)
        {
            return _id > 0 && _id == other.ID ? 0 : 1;
        }

        public virtual string GetState()
        {
        //private IList<Administrator> _administrators;
        //private IList<string> _aliasDomains;
        //private IList<Application> _applications;
        //private IList<Category> _categories;
        //private IList<Content> _content;
        //private DetailTemplate _defaultDetailTemplate;
        //private Locale _defaultLocale;
        //private MasterTemplate _defaultMasterTemplate;
        //private IList<DetailTemplate> _detailTemplates;
        //private string _domain;
        //private IList<Folder> _folders;
        //private int _id;
        //private IList<Locale> _locales;
        //private IList<MasterTemplate> _masterTemplates;
        //private IList<MediaFile> _mediaFiles;
        //private IList<MediaFolder> _mediaFolders;
        //private IList<Menu> _menus;
        //private string _newsletterFolder;
        //private string _noReplyEmail;
        //private bool _online;
        //private IList<Page> _pages;
        //private string _rootMediaFolder;
        //private IList<Stylesheet> _stylesheets;
        //private IList<RssFeed> _rssFeeds;
            return "Domain = " + _domain +
                   ", AliasDomains = " + string.Join(", ", from a in _aliasDomains select a) +
                   ", MasterTemplate = " + string.Join(", ", from mt in _masterTemplates select mt.Name);
        }
    }
}